package org.hackystat.sdsa.analyzer.control.processor;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

import java.util.logging.Logger;

import javax.xml.datatype.XMLGregorianCalendar;

import org.hackystat.sdsa.analyzer.model.activity.Activity;
import org.hackystat.sdsa.analyzer.model.activity.refactoring.BinaryRefactorActivity;
import org.hackystat.sdsa.analyzer.model.activity.refactoring.RefactorActivity;
import org.hackystat.sdsa.analyzer.model.activity.refactoring.UnaryRefactorActivity;
import org.hackystat.sensorbase.resource.sensordata.jaxb.Properties;
import org.hackystat.sensorbase.resource.sensordata.jaxb.Property;
import org.hackystat.sensorbase.resource.sensordata.jaxb.SensorData;
import org.hackystat.utilities.tstamp.Tstamp;
import org.junit.Before;
import org.junit.Test;

/**
 * Tests RefactoringActivityProcessor.
 * 
 * @author hongbing
 */
public class TestRefactoringActivityProcessor {
  /** Refactoring activity processor */
  private RefactoringActivityProcessor processor;
  private Logger logger;
  
  /**
   * Prepares test variables.
   * 
   * @throws Exception If error in testing. 
   */
  @Before public void setUp() throws Exception {
    this.processor = new RefactoringActivityProcessor();
    this.logger = Logger.getLogger(TestRefactoringActivityProcessor.class.getName());
  }

  /**
   * Test the processor of unary refactoring activity.
   * @throws Exception If error occurs
   */
  @Test public void testSingle() throws Exception {
    /** Refactoring data. */
    SensorData refactoringData = new SensorData();
    XMLGregorianCalendar tstamp = Tstamp.makeTimestamp("2007-11-17T10:25:16.949-08:00");
    refactoringData.setTimestamp(tstamp);
    refactoringData.setResource("file:/C:/cvs/work/com/foo/Bar.java");
    refactoringData.setSensorDataType("DevEvent");
    
    // Add property
    Properties props = new Properties();
    refactoringData.setProperties(props);

    Property type = new Property();
    type.setKey("Type");
    type.setValue("Edit");
    props.getProperty().add(type);
    
    Property subType = new Property();
    subType.setKey("Subtype");
    subType.setValue("ProgramUnit");
    props.getProperty().add(subType);

    Property subsubType = new Property();
    subsubType.setKey(RefactorActivity.SUBSUB_TYPE);
    subsubType.setValue("Add");
    props.getProperty().add(subsubType);

    Property unitType = new Property();
    unitType.setKey(RefactorActivity.UNIT_TYPE);
    unitType.setValue("Class");
    props.getProperty().add(unitType);

    Property unitName = new Property();
    unitName.setKey(UnaryRefactorActivity.UNIT_NAME);
    unitName.setValue("Bar");
    props.getProperty().add(unitName);

    EditActivityProcessor editProcessor = new EditActivityProcessor();
    assertFalse("Test processable of document edit activity", 
        editProcessor.processable(refactoringData));

    assertTrue("Test processable of refactoring activity", 
           this.processor.processable(refactoringData));
    
    Activity activity = this.processor.process(refactoringData, this.logger);
    assertTrue("Test return type super", activity instanceof RefactorActivity);
    assertTrue("Test return type unary", activity instanceof UnaryRefactorActivity);
    
    UnaryRefactorActivity refactorActivity = (UnaryRefactorActivity) activity;
    assertEquals("Test resource file", "Bar.java", refactorActivity.getResourceFile());
    assertEquals("Test operator", "ADD", refactorActivity.getOperator().toString());
    assertEquals("Test subject type", "CLASS", refactorActivity.getSubjectType().toString());
    assertEquals("Test subject value", "Bar", refactorActivity.getSubjectName());
  }


  /**
   * Test the processor of binary refactoring activity.
   * @throws Exception If error occurs
   */
  @Test public void testBinary() throws Exception {
    /** Refactoring data. */
    SensorData refactoringData = new SensorData();
    XMLGregorianCalendar tstamp = Tstamp.makeTimestamp("2007-11-17T10:25:16.949-08:00");
    refactoringData.setTimestamp(tstamp);
    refactoringData.setResource("file:/C:/cvs/work/com/foo/Bar.java");
    refactoringData.setSensorDataType("DevEvent");
    
    // Add property
    Properties props = new Properties();
    refactoringData.setProperties(props);

    Property type = new Property();
    type.setKey("Type");
    type.setValue("Edit");
    props.getProperty().add(type);
    
    Property subType = new Property();
    subType.setKey("Subtype");
    subType.setValue("ProgramUnit");
    props.getProperty().add(subType);

    Property subsubType = new Property();
    subsubType.setKey(RefactorActivity.SUBSUB_TYPE);
    subsubType.setValue("Rename");
    props.getProperty().add(subsubType);

    Property unitType = new Property();
    unitType.setKey(RefactorActivity.UNIT_TYPE);
    unitType.setValue("Method");
    props.getProperty().add(unitType);

    Property fromUnitName = new Property();
    fromUnitName.setKey(BinaryRefactorActivity.FROM_UNIT_NAME);
    fromUnitName.setValue("void name()");
    props.getProperty().add(fromUnitName);

    Property toUnitName = new Property();
    toUnitName.setKey(BinaryRefactorActivity.TO_UNIT_NAME);
    toUnitName.setValue("String getName()");
    props.getProperty().add(toUnitName);

    EditActivityProcessor editProcessor = new EditActivityProcessor();
    assertFalse("Test processable of document edit activity", 
        editProcessor.processable(refactoringData));

    assertTrue("Test processable of refactoring activity", 
           this.processor.processable(refactoringData));
    
    Activity activity = this.processor.process(refactoringData, this.logger);
    assertTrue("Test return base", activity instanceof RefactorActivity);
    assertTrue("Test return type binary", activity instanceof BinaryRefactorActivity);
    
    BinaryRefactorActivity refactorActivity = (BinaryRefactorActivity) activity;
    assertEquals("Test resource file", "Bar.java", refactorActivity.getResourceFile());
    assertEquals("Test operator", "RENAME", refactorActivity.getOperator().toString());
    assertEquals("Test subject type", "METHOD", refactorActivity.getSubjectType().toString());
    assertEquals("Test from subject value", "void name()", refactorActivity.getFromSubject());
    assertEquals("Test to subject value", "String getName()", refactorActivity.getToSubject());
  }
}
